﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CSharp.Libs.Database;
using CSharp.Libs.Media;

namespace CSharp.Libs.WPF.UserControls
{
    #region event handlers
    public delegate void FileTagsReceivedEventHandler(object sender, FileTagsReceivedEventArgs e);
    public class FileTagsReceivedEventArgs : EventArgs
    {
    }
    #endregion



    public class DirectoryLister : IDisposable
    {
        #region declarations
        private string _strTagSeparator = "|";

        #region events
        public event FileTagsReceivedEventHandler FileTagsReceived;
        protected void OnFileHashCalculated(
            FileTagsReceivedEventArgs ea)
        {
            if (FileTagsReceived != null)
            {
                FileTagsReceived(this, ea);
            }
        }
        #endregion
        #endregion



        #region constructor
        public DirectoryLister()
        {
        }

        #region dispose pattern (http://www.codeproject.com/Articles/15360/Implementing-IDisposable-and-the-Dispose-Pattern-P)
        // some fields that require cleanup
        private bool disposed = false; // to detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // clean up managed handles here
                }

                disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }
        #endregion
        #endregion



        #region private functions
        private void _loadFileItems(Object data)
        {
            ObservableCollection<FileTaggerListViewItem> ocFileItems = (ObservableCollection<FileTaggerListViewItem>)data;

            //check if a target directory is set
            if (ocFileItems == null)
            {
                //TODO: report error
                return;
            }

            //prepare FileTagger Class
            using (FileTagger ft = new FileTagger()
            {
                Storage = new DataAccessLayer(new SQLiteHandler(
                    string.Concat(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "\\FileTagger.s3db")))
            })
            {
                //run through list
                foreach (FileTaggerListViewItem FileItem in ocFileItems)
                {
                    try
                    {
                        FileObject fo = ft.GetFileObjectForFile(FileItem.FullFileName);
                        ft.GetTagsForFileObject(fo);
                        FileItem.SeparatedTags = _getSeparatedTags(fo);

                        //if (File.Exists(FileItem.FullFileName))
                        //{
                        //    using (FileHashCalculator fhc = new FileHashCalculator())
                        //    {
                        //        fhc.FullFileName = FileItem.FullFileName;
                        //        fhc.CalculateFileHash();
                        //        FileItem.SeparatedTags = fhc.CalculatedHash;
                        //    }
                        //}

                    }
                    catch (Exception)
                    {
                    }
                }
            }
            
            /* sort list:
             http://stackoverflow.com/questions/3309188/c-net-how-to-sort-a-list-t-by-a-property-in-the-object
             
             List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
             */

        }

        private string _getSeparatedTags(
            FileObject fo)
        {
            string strResult = "";

            foreach (TagObject to in fo.Tags)
            {
                strResult = string.Concat(strResult, _strTagSeparator, to.Tag);
            }

            return strResult;
        }
        #endregion



        #region propoerties
        #endregion



        #region methods
        public void LoadFileItems(
            ObservableCollection<FileTaggerListViewItem> FileItems)
        {
            _loadFileItems(FileItems);
        }
        public void LoadFileItemsAsync(
            ObservableCollection<FileTaggerListViewItem> FileItems)
        {
            Thread newThread = new Thread(_loadFileItems);
            newThread.Start(FileItems);
        }
        #endregion
    }
}
